package conversion

import (
	"fmt"
	"strconv"
)

type Num interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}

func Int[T Num](i T) int {
	return int(i)
}
func Int8[T Num](i T) int8 {
	return int8(i)
}
func Int16[T Num](i T) int16 {
	return int16(i)
}
func Int32[T Num](i T) int32 {
	return int32(i)
}
func Int64[T Num](i T) int64 {
	return int64(i)
}
func Uint[T Num](i T) uint {
	return uint(i)
}
func Uint8[T Num](i T) uint8 {
	return uint8(i)
}
func Uint16[T Num](i T) uint16 {
	return uint16(i)
}
func Uint32[T Num](i T) uint32 {
	return uint32(i)
}
func Uint64[T Num](i T) uint64 {
	return uint64(i)
}
func Float32[T Num](i T) float32 {
	return float32(i)
}
func Float64[T Num](i T) float64 {
	return float64(i)
}

func ToString(v any) string {
	return fmt.Sprintf("%v", v)
}
func ToInt(v any) int {
	switch v.(type) {
	case string:
		r, err := strconv.ParseFloat(v.(string), 64)
		if err != nil {
			return 0
		}
		return int(r)
	case int:
		return v.(int)
	case int8:
		return int(v.(int8))
	case int16:
		return int(v.(int16))
	case int32:
		return int(v.(int32))
	case int64:
		return int(v.(int64))
	case uint:
		return int(v.(uint))
	case uint8:
		return int(v.(uint8))
	case uint16:
		return int(v.(uint16))
	case uint32:
		return int(v.(uint32))
	case uint64:
		return int(v.(uint64))
	case float32:
		return int(v.(float32))
	case float64:
		return int(v.(float64))
	case bool:
		if v.(bool) {
			return 1
		} else {
			return 0
		}
	default:
		return 0
	}
}

func ToInt64(v any) int64 {
	switch v.(type) {
	case string:
		r, err := strconv.ParseFloat(v.(string), 64)
		if err != nil {
			return 0
		}
		return int64(r)
	case int:
		return int64(v.(int))
	case int8:
		return int64(v.(int8))
	case int16:
		return int64(v.(int16))
	case int32:
		return int64(v.(int32))
	case int64:
		return v.(int64)
	case uint:
		return int64(v.(uint))
	case uint8:
		return int64(v.(uint8))
	case uint16:
		return int64(v.(uint16))
	case uint32:
		return int64(v.(uint32))
	case uint64:
		return int64(v.(uint64))
	case float32:
		return int64(v.(float32))
	case float64:
		return int64(v.(float64))
	case bool:
		if v.(bool) {
			return 1
		} else {
			return 0
		}
	default:
		return 0
	}
}
